import * as vscode from 'vscode';
import * as fs from 'fs';
import { ContainerManager } from './containerManager';

/**
 * Nginx配置验证器类
 */
export class ConfigValidator {
    private containerManager: ContainerManager;
    private diagnosticCollection: vscode.DiagnosticCollection;

    /**
     * 构造函数
     * @param environment 检测到的环境信息
     */
    constructor(private environment: any) {
        this.containerManager = new ContainerManager(environment);
        this.diagnosticCollection = vscode.languages.createDiagnosticCollection('nginx');
    }

    /**
     * 验证Nginx配置文件
     * @param configPath 配置文件路径
     * @returns 验证结果
     */
    async validateConfig(configPath: string): Promise<{ isValid: boolean; message: string; errorLine?: number; filePath?: string }> {
        try {
            // 检查文件是否存在
            if (!fs.existsSync(configPath)) {
                return {
                    isValid: false,
                    message: `Configuration file not found: ${configPath}`
                };
            }

            // 使用Nginx的-t选项验证配置
            const result = await this.containerManager.validateConfig(configPath);
            
            // 清除之前的诊断信息
            this.clearDiagnostics(configPath);
            
            // 如果验证通过
            if (result.indexOf('syntax is ok') !== -1 && result.indexOf('test is successful') !== -1) {
                return {
                    isValid: true,
                    message: 'Nginx配置语法正确'
                };
            }
            
            // 解析错误信息
            return this.parseErrorMessage(result, configPath);
        } catch (error) {
            console.error('Configuration validation failed:', error);
            return {
                isValid: false,
                message: error instanceof Error ? error.message : String(error)
            };
        }
    }

    /**
     * 监听配置文件变化
     * @param configPath 配置文件路径
     * @param validateOnChange 是否在变化时自动验证
     * @param containerName 关联的容器名称（用于热重载）
     * @returns 文件系统监听器
     */
    watchConfigFile(configPath: string, validateOnChange: boolean = true, containerName?: string): vscode.Disposable {
        const watcher = vscode.workspace.createFileSystemWatcher(configPath);
        
        // 当文件更改时
        watcher.onDidChange(async (uri) => {
            if (validateOnChange) {
                const result = await this.validateConfig(uri.fsPath);
                
                // 如果验证通过且提供了容器名称，尝试热重载
                if (result.isValid && containerName) {
                    try {
                        await this.containerManager.reloadConfig(containerName);
                        vscode.window.showInformationMessage('Nginx配置已热重载');
                    } catch (error) {
                        vscode.window.showErrorMessage(`配置热重载失败: ${error instanceof Error ? error.message : String(error)}`);
                    }
                }
            }
        });
        
        return watcher;
    }

    /**
     * 热重载配置
     * @param configPath 配置文件路径
     * @param containerName 容器名称
     */
    async reloadConfig(configPath: string, containerName: string): Promise<boolean> {
        try {
            // 先验证配置
            const result = await this.validateConfig(configPath);
            
            if (!result.isValid) {
                throw new Error(`配置验证失败: ${result.message}`);
            }
            
            // 重载配置
            await this.containerManager.reloadConfig(containerName);
            return true;
        } catch (error) {
            console.error('Config reload failed:', error);
            throw error;
        }
    }

    /**
     * 解析错误消息
     * @param errorMessage Nginx错误消息
     * @param configPath 配置文件路径
     * @returns 解析结果
     */
    private parseErrorMessage(errorMessage: string, configPath: string): { isValid: boolean; message: string; errorLine?: number; filePath?: string } {
        try {
            // 尝试提取行号和具体错误信息
            const lineRegex = /in .*:(\d+)/;
            const errorRegex = /(.*) in /;
            
            const lineMatch = errorMessage.match(lineRegex);
            const errorMatch = errorMessage.match(errorRegex);
            
            let errorLine = lineMatch ? parseInt(lineMatch[1]) : undefined;
            let message = errorMatch ? errorMatch[1].trim() : errorMessage;
            
            // 提取文件路径
            const filePathRegex = /in\s+([^:]+):/;
            const filePathMatch = errorMessage.match(filePathRegex);
            let filePath = filePathMatch ? filePathMatch[1] : configPath;
            
            // 创建诊断信息
            if (errorLine !== undefined) {
                this.addDiagnostic(filePath, errorLine - 1, message);
            }
            
            return {
                isValid: false,
                message,
                errorLine,
                filePath
            };
        } catch (error) {
            console.error('Error parsing error message:', error);
            return {
                isValid: false,
                message: errorMessage
            };
        }
    }

    /**
     * 添加诊断信息
     * @param filePath 文件路径
     * @param line 行号
     * @param message 错误消息
     */
    private addDiagnostic(filePath: string, line: number, message: string): void {
        try {
            // 创建诊断对象
            const diagnostic = new vscode.Diagnostic(
                new vscode.Range(line, 0, line, 100),
                message,
                vscode.DiagnosticSeverity.Error
            );
            
            // 添加到诊断集合
            const uri = vscode.Uri.file(filePath);
            this.diagnosticCollection.set(uri, [diagnostic]);
            
            // 打开文件并跳转到错误位置
            vscode.workspace.openTextDocument(uri).then(document => {
                vscode.window.showTextDocument(document).then(editor => {
                    const position = new vscode.Position(line, 0);
                    editor.selection = new vscode.Selection(position, position);
                    editor.revealRange(new vscode.Range(position, position));
                });
            });
        } catch (error) {
            console.error('Error adding diagnostic:', error);
        }
    }

    /**
     * 清除诊断信息
     * @param filePath 文件路径
     */
    private clearDiagnostics(filePath: string): void {
        const uri = vscode.Uri.file(filePath);
        this.diagnosticCollection.delete(uri);
    }

    /**
     * 生成示例配置
     * @returns 示例配置内容
     */
    static generateExampleConfig(): string {
        return `
server {
    listen 80;
    server_name localhost;

    gzip on;
    client_max_body_size 10m;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
    }

    location /api {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
`;
    }

    /**
     * 处置资源
     */
    dispose(): void {
        this.diagnosticCollection.dispose();
    }
} 